package com.cskaoyan.demo.typehandler;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/*
   <columnOverride column="ids" javaType="java.lang.Integer[]" typeHandler="JsonIntegerArrayTypeHandler"/>
 */
public class JsonIntegerArrayTypeHandler extends BaseTypeHandler<Integer[]> {
    private static final ObjectMapper mapper = new ObjectMapper();

    /**
     * jdbc过程
     * 1. 获取Connection连接
     * 2. 获取PreparedStatement → connection.prepareStatement(sql)
     *     select * from market_admin where username = ? and password = ?
     *     insert into market_admin(username,password,role_ids) values(?,?,?)
     * 3. preparedStatement.setXXX(index,xxx)
     *        a. 如果是Integer类型的值 → setInteger
     *        b. 如果是String类型的值 → setString
     *        c. index是下标，占位符？的下标
     *        d. 如果给上面的username和password分别赋值 zhangsan和123456
     *        e. preparedStatement.setString(1,"zhangsan") ; preparedStatement.setString(2,"123456")
     *        f. preparedStatement.setString(3,arrayStr) → Integer[]转换为String
     * 4. preparedStatement.executeQuery() → ResultSet
     * 5. resultSet.next() → boolean
     * 6. resultSet.getString("role_ids") → String 转换 Integer[]   封装为admin对象 → admin.setRoleIds(Integer[] roleIds)
     *
     * 在3f和 6 这两步需要做类型的转换，TypeHandler就是做类型转换的
     */

    // 3f
    @Override
    public void setNonNullParameter(PreparedStatement ps, int index, Integer[] parameter, JdbcType jdbcType) throws SQLException {
        // admin.getRoleIds():Integer[] → setString(10,String)
        String str = toJson(parameter);// 使用Jackson帮们转换 Integer[] → String
        ps.setString(index, str);
    }

    // 6
    @Override
    public Integer[] getNullableResult(ResultSet rs, String columnName) throws SQLException {
        //String role_ids = rs.getString("role_ids");
        // admin.setRoleIds(Integer[] roleIds)
        String str = rs.getString(columnName);
        return this.toObject(str);
    }

    @Override
    public Integer[] getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return this.toObject(rs.getString(columnIndex));
    }

    @Override
    public Integer[] getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return this.toObject(cs.getString(columnIndex));
    }

    private String toJson(Integer[] params) {
        try {
            return mapper.writeValueAsString(params);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "[]";
    }

    private Integer[] toObject(String content) {
        if (content != null && !content.isEmpty()) {
            try {
                return (Integer[]) mapper.readValue(content, Integer[].class);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        } else {
            return null;
        }
    }
}
